package com.ease.platform.auditlog.management.impl;

import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ease.access.auditlog.service.AuditLogAccessService;
import com.ease.common.util.ExceptionUtil;
import com.ease.model.system.AuditLog;
import com.ease.model.system.type.AuditLogSeverityType;
import com.ease.platform.auditlog.management.AuditLogManagementService;
import com.ease.platform.auditlog.support.AuditLogContext;
import com.ease.platform.auditlog.vo.AuditLogObject;
import com.ease.platform.authorization.service.impl.AbstractAuthorizationServiceImpl;

/**
 * to avoid auditLogInterceptor aop, so use management.impl instead of service.impl
 * 
 * @author nathanleewei
 * 
 */
public class AuditLogManagementServiceImpl extends AbstractAuthorizationServiceImpl implements AuditLogManagementService {

	private static final transient Log log = LogFactory.getLog(AuditLogManagementServiceImpl.class);

	private AuditLogAccessService auditLogAccessService;

	private AuditLogSeverityType auditLogSeverityType = AuditLogSeverityType.ERROR;

	public void auditMessage() {
		StringBuilder message = prepareMessage();
		auditMessage(AuditLogSeverityType.DEBUG, message);
	}

	public void auditError(Throwable e) {
		StringBuilder message = prepareMessage();
		if (null != e) {
			message.append(ExceptionUtil.write(e));
		}
		auditMessage(AuditLogSeverityType.ERROR, message);
	}

	// public static final int MESSAGE_MAX_LENGTH=32765;//CLOB

	public static final int MESSAGE_MAX_LENGTH = 2998;// varchar2(4000)

	private void auditMessage(AuditLogSeverityType messageSeverity, StringBuilder message) {
		if (null == messageSeverity || messageSeverity.getValue() >= auditLogSeverityType.getValue()) {
			try {
				AuditLog auditLog = (AuditLog) AuditLogContext.getAuditLogContext().getAuditLog();

				String string = message.toString();

				if (null != string) {
					// Caused by: java.sql.SQLException: setString CLOB 只能处理少于 32766 个字符的字符串
					// at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:125)
					if (string.length() >= MESSAGE_MAX_LENGTH) {
						log.warn("message.length = "+string.length()+ " >= " + MESSAGE_MAX_LENGTH);
						string = string.substring(0, MESSAGE_MAX_LENGTH);
					}
				}
				auditLog.setMessage(string);

				auditLog.setAuditLogSeverityType(messageSeverity);
				auditLog.setEndTime(new Date());

				auditLogAccessService.create(auditLog);
			} catch (Exception e) {
				log.error("auditMessage", e);
			} finally {
				// TODO AuditLogContext.remove();
			}
		}
	}

	private StringBuilder prepareMessage() {
		AuditLogContext auditLogContext = AuditLogContext.getAuditLogContext();

		StringBuilder message = new StringBuilder();
		if (notEmpty(auditLogContext.getAuditLogObjects())) {
			for (AuditLogObject auditLogObject : auditLogContext.getAuditLogObjects()) {
				message.append(auditLogObject.getMessage());
			}
		}
		return message;

	}

	/**
	 * @return the auditLogSeverityType
	 */
	public AuditLogSeverityType getAuditLogSeverityType() {
		return auditLogSeverityType;
	}

	/**
	 * @param auditLogSeverityType
	 *            the auditLogSeverityType to set
	 */
	public void setAuditLogSeverityType(AuditLogSeverityType auditLogSeverityType) {
		this.auditLogSeverityType = auditLogSeverityType;
	}

	/**
	 * @return the auditLogAccessService
	 */
	public AuditLogAccessService getAuditLogAccessService() {
		return auditLogAccessService;
	}

	/**
	 * @param auditLogAccessService
	 *            the auditLogAccessService to set
	 */
	public void setAuditLogAccessService(AuditLogAccessService auditLogAccessService) {
		this.auditLogAccessService = auditLogAccessService;
	}
}
